﻿#region Using Directives
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#endregion

namespace Nihongo
{
    public class BasicRomajiRenderer : IRomajiRenderer
    {
        public string Render(ILanguageComponent word)
        {
            return ConvertKanaToRomaji(word.Kana);
        }

        public string Render(Sentence sentence)
        {
            StringBuilder romaji = new StringBuilder();

            foreach (Word word in sentence)
            {
                romaji.Append(ConvertKanaToRomaji(word.Kana));
            }

            return romaji.ToString();
        }

        private static string ConvertKanaToRomaji(string kana)
        {
            StringBuilder romaji = new StringBuilder();

            for (int i = 0; i < kana.Length; i++)
            {

                char current = kana[i];
                char next = (i < kana.Length - 1) ? kana[i + 1] : ' ';
                string currentRomaji = ConvertCharToRomaji(current);

                romaji.Append(currentRomaji);

                if (next == 'ー')
                {
                    romaji.Append(currentRomaji.Substring(currentRomaji.Length - 1));
                    i++;
                }
                else if (next == 'っ' || next == 'ッ')
                {
                    romaji.Append((i < kana.Length - 2) ? ConvertCharToRomaji(kana[i + 2]).Substring(0, 1) : "");
                    i++;
                }
                else if (next == 'ゃ' || next == 'ャ' || next == 'ゅ' || next == 'ュ' || next == 'ょ' || next == 'ョ')
                {
                    romaji.Remove(romaji.Length - 1, 1);

                    if (next == 'ゃ' || next == 'ャ')
                    {
                        romaji.Append("a");                     
                    }
                    else if (next == 'ゅ' || next == 'ュ')
                    {
                        romaji.Append("u");
                    }
                    else if (next == 'ょ' || next == 'ョ')
                    {
                        if (current == 'し' || current == 'シ' || current == 'ち' || current == 'チ')
                        {
                            romaji.Append("o");
                        }
                        else
                        {
                            romaji.Append("yo");
                        }
                    }

                    next = (++i < kana.Length - 1) ? kana[i + 1] : ' ';
                    if (next == 'ー')
                    {
                        romaji.Append(romaji[currentRomaji.Length - 1]);
                        i++;
                    }
                }
            }

            return romaji.ToString();
        }

        private static string ConvertCharToRomaji(char c)
        {
            if (c == 'あ' || c == 'ア') return "a";
            if (c == 'い' || c == 'イ') return "i";
            if (c == 'う' || c == 'ウ') return "u";
            if (c == 'え' || c == 'エ') return "e";
            if (c == 'お' || c == 'オ') return "o";

            if (c == 'か' || c == 'カ') return "ka";
            if (c == 'き' || c == 'キ') return "ki";
            if (c == 'く' || c == 'ク') return "ku";
            if (c == 'け' || c == 'ケ') return "ke";
            if (c == 'こ' || c == 'コ') return "ko";

            if (c == 'が' || c == 'ガ') return "ga";
            if (c == 'ぎ' || c == 'ギ') return "gi";
            if (c == 'ぐ' || c == 'グ') return "gu";
            if (c == 'げ' || c == 'ゲ') return "ge";
            if (c == 'ご' || c == 'ゴ') return "go";

            if (c == 'さ' || c == 'サ') return "sa";
            if (c == 'し' || c == 'シ') return "shi";
            if (c == 'す' || c == 'ス') return "su";
            if (c == 'せ' || c == 'セ') return "se";
            if (c == 'そ' || c == 'ソ') return "so";

            if (c == 'じ' || c == 'ジ') return "ji";

            if (c == 'た' || c == 'タ') return "ta";
            if (c == 'ち' || c == 'チ') return "chi";
            if (c == 'つ' || c == 'ツ') return "tsu";
            if (c == 'て' || c == 'テ') return "te";
            if (c == 'と' || c == 'ト') return "to";

            if (c == 'な' || c == 'ナ') return "na";
            if (c == 'に' || c == 'ニ') return "ni";
            if (c == 'ぬ' || c == 'ヌ') return "nu";
            if (c == 'ね' || c == 'ネ') return "ne";
            if (c == 'の' || c == 'ノ') return "no";

            if (c == 'は' || c == 'ハ') return "ha";
            if (c == 'ひ' || c == 'ヒ') return "hi";
            if (c == 'ふ' || c == 'フ') return "fu";
            if (c == 'へ' || c == 'ヘ') return "he";
            if (c == 'ほ' || c == 'ホ') return "ho";

            if (c == 'ぱ' || c == 'パ') return "pa";
            if (c == 'ぴ' || c == 'ピ') return "pi";
            if (c == 'ぷ' || c == 'プ') return "pu";
            if (c == 'ぺ' || c == 'ペ') return "pe";
            if (c == 'ぽ' || c == 'ポ') return "po";

            if (c == 'ば' || c == 'バ') return "ba";
            if (c == 'び' || c == 'ビ') return "bi";
            if (c == 'ぶ' || c == 'ブ') return "bu";
            if (c == 'べ' || c == 'ベ') return "be";
            if (c == 'ぼ' || c == 'ボ') return "bo";

            if (c == 'ま' || c == 'マ') return "ma";
            if (c == 'み' || c == 'ミ') return "mi";
            if (c == 'む' || c == 'ム') return "mu";
            if (c == 'め' || c == 'メ') return "me";
            if (c == 'も' || c == 'モ') return "mo";

            if (c == 'や' || c == 'ヤ') return "ya";
            if (c == 'ゆ' || c == 'ユ') return "yu";
            if (c == 'よ' || c == 'ヨ') return "yo";

            if (c == 'ら' || c == 'ラ') return "ra";
            if (c == 'り' || c == 'リ') return "ri";
            if (c == 'る' || c == 'ル') return "ru";
            if (c == 'れ' || c == 'レ') return "re";
            if (c == 'ろ' || c == 'ロ') return "ro";

            if (c == 'わ' || c == 'ワ') return "wa";
            if (c == 'を' || c == 'ヲ') return "wo";

            if (c == 'ん' || c == 'ン') return "n";

            return string.Empty;
        }
    }
}
